diff options
| author | Fuwn <[email protected]> | 2026-02-10 01:08:11 -0800 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2026-02-10 01:08:11 -0800 |
| commit | 920d22332069f1ca60740c290173a95846fb38c3 (patch) | |
| tree | 5909cecde94bf1acd83385a5b3d789175f2713f0 /apps/web/app/shared/[token] | |
| parent | fix: service worker cross-origin image handling and CI env vars (diff) | |
| download | asa.news-920d22332069f1ca60740c290173a95846fb38c3.tar.xz asa.news-920d22332069f1ca60740c290173a95846fb38c3.zip | |
feat: scoped mark-all-read, share enhancements, notification z-index
- Mark all as read now scopes to current feed/folder instead of all
- Added undo button to mark-all-read toast notification
- Share notes can be toggled between public and private visibility
- Track share view count and display in shares list
- Activity-based share expiry: views reset the expiry timer
- Fixed notification panel z-index layering behind content area
Diffstat (limited to 'apps/web/app/shared/[token]')
| -rw-r--r-- | apps/web/app/shared/[token]/page.tsx | 31 |
1 files changed, 29 insertions, 2 deletions
diff --git a/apps/web/app/shared/[token]/page.tsx b/apps/web/app/shared/[token]/page.tsx index eaab4f1..b913721 100644 --- a/apps/web/app/shared/[token]/page.tsx +++ b/apps/web/app/shared/[token]/page.tsx @@ -17,8 +17,13 @@ interface SharedHighlightData { } interface SharedEntryRow { + id: string entry_id: string expires_at: string | null + note: string | null + note_is_public: boolean + view_count: number + expiry_interval_days: number highlighted_text: string | null highlight_text_offset: number | null highlight_text_length: number | null @@ -45,7 +50,7 @@ async function fetchSharedEntry(token: string) { const { data, error } = await adminClient .from("shared_entries") .select( - "entry_id, expires_at, highlighted_text, highlight_text_offset, highlight_text_length, highlight_text_prefix, highlight_text_suffix, entries!inner(id, title, url, author, summary, content_html, published_at, enclosure_url, feeds!inner(title))" + "id, entry_id, expires_at, note, note_is_public, view_count, expiry_interval_days, highlighted_text, highlight_text_offset, highlight_text_length, highlight_text_prefix, highlight_text_suffix, entries!inner(id, title, url, author, summary, content_html, published_at, enclosure_url, feeds!inner(title))" ) .eq("share_token", token) .maybeSingle() @@ -73,7 +78,24 @@ async function fetchSharedEntry(token: string) { } } - return { expired: false as const, entry: row.entries, highlightData } + const publicNote = row.note_is_public && row.note ? row.note : null + + const expiryIntervalDays = row.expiry_interval_days ?? 7 + const newExpiresAt = new Date( + Date.now() + expiryIntervalDays * 24 * 60 * 60 * 1000 + ).toISOString() + + adminClient + .from("shared_entries") + .update({ + view_count: row.view_count + 1, + last_viewed_at: new Date().toISOString(), + expires_at: newExpiresAt, + }) + .eq("id", row.id) + .then(() => {}) + + return { expired: false as const, entry: row.entries, highlightData, publicNote } } export async function generateMetadata({ @@ -142,6 +164,11 @@ export default async function SharedPage({ params }: SharedPageProperties) { {entry.author && <span> · {entry.author}</span>} {formattedDate && <span> · {formattedDate}</span>} </div> + {result.publicNote && ( + <blockquote className="mb-6 border-l-2 border-border pl-4 text-text-secondary italic"> + {result.publicNote} + </blockquote> + )} {entry.enclosure_url && ( <div className="mb-4 border border-border p-3"> <audio |